/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ant.internal.ui.preferences; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.ant.core.IAntClasspathEntry; import org.eclipse.ant.internal.core.AntObject; import org.eclipse.ant.internal.ui.AntUIPlugin; import org.eclipse.ant.internal.ui.ColumnSorter; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ColumnLayoutData; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.PlatformUI; /** * Provides the generic implementation for a sub-page in the Ant preference page. */ public abstract class AntPage { protected static final int ADD_BUTTON = IDialogConstants.CLIENT_ID + 1; protected static final int EDIT_BUTTON = IDialogConstants.CLIENT_ID + 2; protected static final int REMOVE_BUTTON = IDialogConstants.CLIENT_ID + 3; protected SelectionAdapter selectionAdapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { buttonPressed(((Integer) e.widget.getData()).intValue()); } }; private AntRuntimePreferencePage preferencePage; private TableViewer tableViewer; private AntContentProvider contentProvider; private AntObjectLabelProvider labelProvider = new AntObjectLabelProvider(); protected Button editButton; protected Button removeButton; private final String[] fTableColumnHeaders = { AntPreferencesMessages.AntPage_0, AntPreferencesMessages.AntPage_1, AntPreferencesMessages.AntPage_2, AntPreferencesMessages.AntPage_3 }; private final ColumnLayoutData[] fTableColumnLayouts = { new ColumnWeightData(33), new ColumnWeightData(23), new ColumnWeightData(22), new ColumnWeightData(22) }; /** * Creates an instance of this page. */ public AntPage(AntRuntimePreferencePage preferencePage) { super(); this.preferencePage = preferencePage; } /** * Adds buttons specific to the page. */ protected abstract void addButtonsToButtonGroup(Composite parent); /** * Give this page a chance to initialize itself */ protected abstract void initialize(); /** * Adds an object to the contents */ protected void addContent(Object o) { if (contentProvider != null) { contentProvider.add(o); } } /* * (non-Javadoc) * * @see org.eclipse.ant.internal.ui.preferences.AntPage#buttonPressed(int) */ private void buttonPressed(int buttonId) { switch (buttonId) { case ADD_BUTTON: add(); break; case EDIT_BUTTON: edit(getSelection()); break; case REMOVE_BUTTON: remove(); break; default: break; } } /** * Creates and returns a button with appropriate size and layout. * * @param parent * the control to create the button on * @param labelKey * the key to lookup the button's label * @param buttonId * the id to assign to this button * @return a new and initialized button */ protected Button createPushButton(Composite parent, String buttonText, int buttonId) { Button button = new Button(parent, SWT.PUSH); button.setFont(parent.getFont()); button.setText(buttonText); button.setData(new Integer(buttonId)); button.addSelectionListener(selectionAdapter); preferencePage.setButtonLayoutData(button); return button; } /** * Creates the group which will contain the buttons. */ protected void createButtonGroup(Composite top) { Composite buttonGroup = new Composite(top, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; buttonGroup.setLayout(layout); buttonGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL)); buttonGroup.setFont(top.getFont()); addButtonsToButtonGroup(buttonGroup); } /** * Creates the table viewer. */ protected void createTable(Composite parent) { Table table = new Table(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER); GridData data = new GridData(GridData.FILL_BOTH); data.widthHint = 425; data.heightHint = table.getItemHeight(); data.horizontalSpan = 1; table.setLayoutData(data); table.setFont(parent.getFont()); TableLayout tableLayout = new TableLayout(); table.setLayout(tableLayout); table.setHeaderVisible(true); table.setLinesVisible(true); contentProvider = getContentProvider(); tableViewer = new TableViewer(table); tableViewer.setContentProvider(contentProvider); tableViewer.setLabelProvider(this.labelProvider); tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { tableSelectionChanged((IStructuredSelection) event.getSelection()); } }); tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (!event.getSelection().isEmpty() && editButton.isEnabled()) { edit((IStructuredSelection) event.getSelection()); } } }); ArrayList<ColumnSorter> sorters = new ArrayList<>(fTableColumnHeaders.length); for (int i = 0; i < fTableColumnHeaders.length; i++) { tableLayout.addColumnData(fTableColumnLayouts[i]); TableColumn column = new TableColumn(table, SWT.NONE, i); column.setResizable(fTableColumnLayouts[i].resizable); column.setText(fTableColumnHeaders[i]); sorters.add(new ColumnSorter(this.tableViewer, column) { @Override public String getCompareText(Object obj, int columnindex) { return AntPage.this.labelProvider.getColumnText(obj, columnindex); } }); } table.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent event) { if (editButton.isEnabled() && event.character == SWT.DEL && event.stateMask == 0) { remove(tableViewer); } } }); restoreColumnSettings(AntUIPlugin.getDefault().getDialogSettings(), sorters); } /** * Persist table settings into the give dialog store, prefixed with the given key. * * @param settings * dialog store * @since 3.5 */ public void saveColumnSettings(IDialogSettings settings) { Table table = this.tableViewer.getTable(); int columnCount = table.getColumnCount(); for (int i = 0; i < columnCount; i++) { settings.put(getHelpContextId() + ".columnWidth" + i, table.getColumn(i).getWidth()); //$NON-NLS-1$ } TableColumn column = table.getSortColumn(); if (column != null) { settings.put(getHelpContextId() + ".sortColumn", table.indexOf(column)); //$NON-NLS-1$ settings.put(getHelpContextId() + ".sortDirection", table.getSortDirection()); //$NON-NLS-1$ } } /** * Restore table settings from the given dialog store using the given key. * * @param settings * dialog settings store * @since 3.5 */ private void restoreColumnSettings(IDialogSettings settings, ArrayList<ColumnSorter> sorters) { restoreColumnWidths(settings); int idx = 0; int direction = SWT.DOWN; try { idx = settings.getInt(getHelpContextId() + ".sortColumn"); //$NON-NLS-1$ direction = settings.getInt(getHelpContextId() + ".sortDirection"); //$NON-NLS-1$ } catch (NumberFormatException e) { // do nothing } Table table = this.tableViewer.getTable(); if (table.getColumnCount() < 1) { return; } TableColumn column = table.getColumn(idx); if (column != null) { table.setSortColumn(column); table.setSortDirection(direction); ColumnSorter sorter = sorters.get(idx); sorter.setDirection(direction); } sorters.clear(); } /** * Restores the column widths from dialog settings * * @param settings * @since 3.5 */ private void restoreColumnWidths(IDialogSettings settings) { Table table = this.tableViewer.getTable(); int columnCount = table.getColumnCount(); for (int i = 0; i < columnCount; i++) { int width = -1; try { width = settings.getInt(getHelpContextId() + ".columnWidth" + i); //$NON-NLS-1$ } catch (NumberFormatException e) { // do nothing } if ((width <= 0) || (i == table.getColumnCount() - 1)) { table.getColumn(i).pack(); } else { table.getColumn(i).setWidth(width); } } } /** * Returns the content provider to use for the table viewer * * @return AntPageContentProvider */ protected AntContentProvider getContentProvider() { return new AntContentProvider(false); } /** * Returns the currently listed objects in the table if the library for that entry is still included in the preferences. Default objects are * included depending on the value of the <code>forDisplay</code> parameter. Returns <code>null</code> if this widget has not yet been created or * has been disposed. * * @param forDisplay * Whether the result is to be displayed in the UI or stored in the preferences * @return The list of objects currently displayed in the table */ protected List<Object> getContents(boolean forDisplay) { if (tableViewer == null || tableViewer.getControl().isDisposed()) { return null; } List<IAntClasspathEntry> entries = getPreferencePage().getLibraryEntries(); Object[] elements = contentProvider.getElements(tableViewer.getInput()); List<Object> contents = new ArrayList<>(elements.length); Object element; AntObject antObject; for (int i = 0; i < elements.length; i++) { element = elements[i]; if (element instanceof AntObject) { antObject = (AntObject) element; if (forDisplay) { if (!antObject.isDefault() && !entries.contains(antObject.getLibraryEntry())) { continue; } } else if (antObject.isDefault() || !entries.contains(antObject.getLibraryEntry())) { continue; } } contents.add(element); } return contents; } /** * Returns the selection in the viewer, or <code>null</code> if none. */ protected final IStructuredSelection getSelection() { if (tableViewer == null || tableViewer.getControl().isDisposed()) { return null; } return ((IStructuredSelection) tableViewer.getSelection()); } /** * Returns the shell of the sub-page. */ protected final Shell getShell() { if (tableViewer == null || tableViewer.getControl().isDisposed()) { return null; } return tableViewer.getControl().getShell(); } /** * Handles the remove button pressed event */ protected void remove() { remove(tableViewer); } protected void remove(TableViewer viewer) { AntContentProvider antContentProvider = (AntContentProvider) viewer.getContentProvider(); IStructuredSelection sel = (IStructuredSelection) viewer.getSelection(); Iterator<?> itr = sel.iterator(); while (itr.hasNext()) { antContentProvider.remove(itr.next()); } } /** * Sets the contents of the table on this page. Has no effect if this widget has not yet been created or has been disposed. */ protected void setInput(List<?> inputs) { if (tableViewer == null || tableViewer.getControl().isDisposed()) { return; } tableViewer.setInput(inputs); tableSelectionChanged((IStructuredSelection) tableViewer.getSelection()); } /** * Updates the content element in the table viewer. */ protected final void updateContent(Object element) { if (tableViewer == null || tableViewer.getControl().isDisposed()) { return; } tableViewer.update(element, null); } /** * Creates the default contents of this page */ protected Composite createContents(Composite top) { PlatformUI.getWorkbench().getHelpSystem().setHelp(top, getHelpContextId()); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 2; layout.marginWidth = 2; top.setLayout(layout); top.setLayoutData(new GridData(GridData.FILL_BOTH)); createTable(top); createButtonGroup(top); return top; } protected AntRuntimePreferencePage getPreferencePage() { return preferencePage; } protected TableViewer getTableViewer() { return tableViewer; } /** * Handles selection changes in the table viewer. */ protected void tableSelectionChanged(IStructuredSelection newSelection) { int size = newSelection.size(); boolean enabled = true; Iterator<?> itr = newSelection.iterator(); while (itr.hasNext()) { Object element = itr.next(); if (element instanceof AntObject) { AntObject antObject = (AntObject) element; if (antObject.isDefault()) { enabled = false; break; } } } editButton.setEnabled(enabled && size == 1); removeButton.setEnabled(enabled && size > 0); } /** * Allows the user to edit a custom Ant object. * * @param selection * The selection containing the object to edit */ protected abstract void edit(IStructuredSelection selection); /** * Allows the user to add a custom Ant object. * */ protected abstract void add(); /** * Returns this page's help context id, which is hooked to this page on creation. * * @return help context id */ protected abstract String getHelpContextId(); protected void connectToFolder(final TabItem item, TabFolder folder) { folder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (e.item == item) { // remove ant objects whose library has been removed setInput(getContents(true)); } } }); } }